<?php

/**
 *
 * PHP version 5
 *
 * @author     Thomas Breuss <thomas.breuss@gmx.ch>
 * @copyright  2006 Thomas Breuss <thomas.breuss@gmx.ch>
 */
abstract class WSB_Node
{

	/**
	 * @var array
	 */
	protected $_vars = array();

	/**
	 * @var WSB_Node
	 */
	protected $parent	= NULL;

	/**
	 * @var array
	 */
	protected $children	= array();

	/**
	 * @return integer
	 */
	abstract public function getId();

	/**
	 * @return integer
	 */
	abstract public function getParentId();

	/**
	 * @param string $key
	 * @param mixed $val
	 */
    public function __set($key, $val)
	{
   		$this->_vars[$key] = $val;
    }

    /**
     * @param string $key
     * @return mixed
     */
    public function __get($key)
	{
		return isset($this->_vars[$key]) ? $this->_vars[$key] : null;
    }

    /**
     * @param string $key
     * @return boolean
     */
    public function __isset($key)
	{
		return isset($this->_vars[$key]);
    }

    /**
     * @param string $key
     */
    public function __unset($key)
	{
        unset($this->_vars[$key]);
    }

    /**
     * Adds a child to this node
     *
     * @param WSB_Node $node
     * @return    void
     */
	public function addChild(WSB_Node $node)
	{
		$this->children[] = $node;
	}

    /**
     * Return true if the node has children, otherwise false.
     *
     * @return	boolean
     */
	public function hasChildren()
	{
		return $this->getChildrenCount() > 0 ? true : false;
	}

	/**
	 * Return children of the node
	 *
	 * @return array
	 */
	public function getChildren()
	{
		return $this->children;
	}

	/**
	 * Return true if the node has a parent, otherwise false.
	 *
	 * @return	boolean
	 */
	public function hasParent()
	{
		return ($this->parent != NULL);
	}

    /**
     * Returns the number of children of the current node.
     *
     * @return    integer
     */
	public function getChildrenCount()
	{
		return count($this->children);
	}

	/**
	 * Return the number of the parent's children (the number of my sisters including me)
	 *
	 * @return integer
	 */
	public function getParentsChildrenCount()
	{
		if($this->hasParent()) {
			$parent =& $this->getParent();
			return count($parent->children);
		}
		return 0;
	}

    /**
     * Return true if the current node has an upper neighbor (or a sister/brother)
     *
     * @return    boolean
     */
	public function hasUpper()
	{
		if($this->getNodeIndex() > 0) {
			return true;
		}
		return false;
	}

	/**
	 * Get the upper (neigbor) node
	 *
	 * @return WSB_Node
	 */
	public function getUpper()
	{
		if($this->hasParent()) {
			$index = $this->getNodeIndex() - 1;
			return $this->getParent()->children[$index];
		}
	}

    /**
     * Returns true if the current node has a lower neighbor (or a sister/brother)
     *
     * @return    boolean
     */
	public function hasLower() 	{
		if(($this->getNodeIndex() + 1) <  $this->getParentsChildrenCount()) {
			return true;
		}
		return false;
	}

	/**
	 * Get the lower (neigbor) node
	 *
	 * @return WSB_Node
	 */
	public function getLower()
	{
		if($this->hasParent()) {
			$index = $this->getNodeIndex() + 1;
			return $this->getParent()->children[$index];
		}
	}

    /**
     * Returns true if the current node has a lower or an upper neighbor (or a sister/brother)
     *
     * @return    boolean
     */
	public function hasNeighbours()
	{
		if($this->hasLower() || $this->hasUpper()) {
			return true;
		}
		return false;
	}

    /**
     * Get the array index of the current node.
     * This value is equal to the sort var coming from the databes table pages!!!!!
     *
     * @return    integer
     */
	public function getNodeIndex()
	{
		if($this->hasParent()) {
			$parent =& $this->parent;
			foreach($parent->children AS $index=>$child) {
				if($child->ID == $this->ID) {
					return $index;
				}
			}
		}
		return 0;
	}

    /**
     * Return the level of the current node.
     *
     * @return    integer
     */
	public function getLevel()
	{
        $level = 0;
        $node = $this;
        while($node->parent != NULL) {
        	$node = $node->parent;
        	$level++;
        }
        return $level;
	}

    /**
     * Return the parent of the current node.
     *
     * @return WSB_Node
     */
	public function getParent()
	{
        return $this->parent;
	}

    /**
     * Return true if current node is root.
     *
     * @return    boolean
     */
	public function isRoot()
	{
        return $this->parent==NULL;
	}

	/**
	 * Return the first child of a node
	 *
	 * @return WSB_Node
	 */
	public function getFirstChild()
	{
		if($this->hasChildren()) {
			return $this->children[0];
		} else {
			return NULL;
		}
	}

	/**
	 * Return node data as array.
	 *
	 * @return array
	 */
	public function toArray()
	{
		return $this->_vars;
	}

}
